package com.duowan.cms.parser.util;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.duowan.cms.common.util.PathUtil;
import com.duowan.cms.core.rmi.client.channel.ChannelRemoteService;
import com.duowan.cms.core.rmi.client.template.TemplateRemoteService;
import com.duowan.cms.common.util.MD5;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.common.webapp.content.SpringApplicationContextHolder;
import com.duowan.cms.common.webapp.property.ExtendedPropertyPlaceholderConfigurer.PropertiesHolder;
import com.duowan.cms.dto.channel.ChannelInfo;
import com.duowan.cms.dto.template.TemplateCategory;
import com.duowan.cms.dto.template.TemplateInfo;

/**
 * 用户自定义语法解析器
 * 
 * 解析用户自定义语法. 如：静态页面include {[包含=/aa.html]}、模板引用
* {[模板=模板中文名]}或者{[模板=频道中文名:模板中文名]}、关键字url {[关键字=频道中文名:关键字]}
* {[关键字=关键字]}本频道的关键字
 *
 * <br>==========================
 * <br> 公司：欢聚时代
 * <br> 开发：qiusidi@yy.com
 * <br> 版本：1.0
 * <br> 创建时间：2012-10-23
 * <br>==========================
 */
public class UserDefinedSyntaxParser {

    public final Log logger = LogFactory.getLog(UserDefinedSyntaxParser.class);

    // 分页
    public final static String SPLIT_LINE = "split_line";

    private static UserDefinedSyntaxParser parser = new UserDefinedSyntaxParser();

    public static UserDefinedSyntaxParser getInstance() {
        return parser;
    }

    private UserDefinedSyntaxParser() {
    }

    /**
     * 解析模板内容中查找设置的pagesize
     * 
     * @param content
     * @param pagesize
     * @return
     */
    public int getPageSizeFromContent(String content) {
        int pagesize = 0;
        String regexp = "#set[\\s]*\\(\\$len[\\s]*=([\\d]+)[\\s]*\\)";
        Pattern pageSizePattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
        Matcher matcher = pageSizePattern.matcher(content);
        if (matcher.find()) {
            try {
                pagesize = Integer.parseInt(matcher.group(1));
            } catch (NumberFormatException e) {
                logger.warn(matcher.group(1) + "转化为数字出错!", e);
                pagesize = 0;
            }
        }
        return pagesize;
    }

    /**
     * 解析内容中的分页数语法：{[分页数=totalPage, pageSize]}
     * @param content
     * @return List:
     * 1.被替换的内容
     * 2.分页数
     * 3.每页的记录数(可能不存在)
     */
    public List<String> parsePaging(String content) {
        List<String> list = new ArrayList<String>();
        Pattern pattern = Pattern.compile("\\{\\[分页数=([^\\]]+)\\]\\}", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
        Matcher m = pattern.matcher(content);
        if (m.find()) {
            content = content.replaceFirst("\\{\\[分页数=([^\\]]+)\\]\\}", "");
            list.add(content);
            String[] arguments = m.group(1).split(",");
            for (String argument : arguments) {
                list.add(argument);
            }
        }
        return list;
    }

    /**
     * 解析模板的“模板引用”语法，返回解析后的结果
     * 
     * @param channelInfo
     * @param templateInfo
     * @param html
     * @return
     */
    public String parseTemplateQuote(ChannelInfo channelInfo, TemplateInfo templateInfo, String html) {
        String result = "";
        String channelId = channelInfo.getId();
        Long templateId = templateInfo.getId();
        StringBuffer sb = new StringBuffer();
        Pattern pattern = Pattern.compile(".*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        Matcher matcher = pattern.matcher(html);

        String regexTemplateHead = "\\{\\[";
        String regexTemplateTail = "\\]\\}";
        String regexTemplate = regexTemplateHead + "([^=]+)=([^\\]]+)" + regexTemplateTail;// 正则，解析模板引用的标签
        String parserStr = "";// 自定义标签解析结果

        while (matcher.find()) {
            parserStr = matcher.group(0);// 自定义标签等于号左边字符

            Pattern patternParser = Pattern.compile(regexTemplate, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
            Matcher matcherParser = patternParser.matcher(parserStr);

            while (matcherParser.find()) {
                String syntax = matcherParser.group(0);// 整个语法
                String leftSyntax = matcherParser.group(1);// 等号左边
                String rightSyntax = matcherParser.group(2);// 等号右边

                if (!StringUtil.isEmpty(leftSyntax) && !StringUtil.isEmpty(rightSyntax)) {
                    String replacement = "";// 替换物
                    if (leftSyntax.indexOf("注释") != -1) {
                        replacement = "";
                    } else if (leftSyntax.equals("包含")) {
                        replacement = "<!--#include virtual=\"" + rightSyntax + "\"-->";
                    } else if (leftSyntax.equals("模板")) {
                        String templateName = rightSyntax;
                        TemplateInfo tempTemplateInfo = this.getTemplateRemoteService().getByChannelIdAndTemplateName(channelInfo.getId(), templateName);
                        if (tempTemplateInfo != null) {
                            replacement = this.getTemplateInclude(channelInfo, tempTemplateInfo);
                        }
                    } else if (leftSyntax.equals("绝对模板")) {
                        // TODO 模板和绝对模板的区别
                        String templateName = rightSyntax;
                        TemplateInfo tempTemplateInfo = this.getTemplateRemoteService().getByChannelIdAndTemplateName(channelInfo.getId(), templateName);
                        replacement = this.getTemplateInclude(channelInfo, tempTemplateInfo);
                    } else if (leftSyntax.equals("公共模板")) {
                        String[] rightSyntaxArr = rightSyntax.split(":");
                        if (rightSyntaxArr.length == 2) {
                            String tempChannnelName = rightSyntaxArr[0];
                            ChannelInfo tempChannelInfo = this.getChannelRemoteService().getByName(tempChannnelName);
                            if (tempChannelInfo != null) {
                                String templateName = rightSyntaxArr[1];
                                TemplateInfo tempTemplateInfo = this.getTemplateRemoteService().getByChannelIdAndTemplateName(tempChannelInfo.getId(), templateName);
                                replacement = this.getTemplateInclude(tempChannelInfo, tempTemplateInfo);
                            }
                        } else {
                            logger.warn("公共模板语法有误：" + rightSyntax + ", 在频道channelId=" + channelId + ", 模板templateId=" + templateId + "中。");
                        }
                    } else if (leftSyntax.equals("js模板")) {
                        String templateName = rightSyntax;
                        TemplateInfo tempTemplateInfo = this.getTemplateRemoteService().getByChannelIdAndTemplateName(channelInfo.getId(), templateName);
                        replacement = this.getJsTemplateInclude(channelInfo, tempTemplateInfo);
                    } else if (leftSyntax.equals("关键字")) {
                        // TODO 该功能暂时不需要再支持
                    } else if (leftSyntax.equals("回复")) {
                        // TODO 该功能暂时不需要再支持
                        // replacement = this.getCommentInclude(channelInfo,
                        // Long.parseLong(rightSyntax.substring(rightSyntax.lastIndexOf("/")
                        // + 1, rightSyntax.lastIndexOf("."))));
                    } else if (leftSyntax.equals("投票")) {
                        // TODO 该功能暂时不需要再支持
                    } else if (leftSyntax.equals("投票结果")) {
                        String[] rightSyntaxArr = rightSyntax.split(":");
                        if (rightSyntaxArr.length == 2) {
                            String tempChannelName = rightSyntaxArr[0];
                            ChannelInfo tempChannelInfo = this.getChannelRemoteService().getByName(rightSyntaxArr[0]);
                            if (tempChannelInfo != null) {
                                // TODO 该功能暂时不需要再支持
                            }
                        } else {
                            logger.warn("投票结果语法有误：" + rightSyntax + ", 在频道channelId=" + channelId + ", 模板templateId=" + templateId + "中。");
                        }
                    } else if (leftSyntax.equals("动态公共模板")) {
                        String publicTemplateName = rightSyntax; // 等号右边
                                                                 // 公共频道模板名，即是公共频道的某个模板的名字
                        TemplateInfo tempTemplateInfo = this.getTemplateRemoteService().getByChannelIdAndTemplateName("public", publicTemplateName);
                        if (tempTemplateInfo != null) {
                            replacement = tempTemplateInfo.getContent();
                        } else {
                            logger.warn("动态公共模板语法有误：" + publicTemplateName + ", 模板[name=" + publicTemplateName + "]不在公共频道模板中。");
                        }
                    }
                    // 替换自定义语法
                    parserStr = parserStr.replace(syntax, replacement);
                }
            }
            sb.append(parserStr + "\n");
        }
        pattern = Pattern.compile("(\\n){2,}", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        result = pattern.matcher(sb.toString()).replaceAll("\n");
        return result;
    }

    private ChannelRemoteService getChannelRemoteService() {
        return SpringApplicationContextHolder.getBean("channelRemoteService", ChannelRemoteService.class);
    }

    private TemplateRemoteService getTemplateRemoteService() {
        return SpringApplicationContextHolder.getBean("templateRemoteService", TemplateRemoteService.class);
    }

    // 得到通过评论的js字符串
    public String getCommentInclude(ChannelInfo channelInfo, Long articleId) {
        String comment3Uniqid = "var comment3Uniqid = '" + new MD5().get(PathUtil.getArticleOnlineUrl(channelInfo.getDomain(), articleId)).toLowerCase() + "';";
        String common_comment = "<script>" + comment3Uniqid + "</script><a name='comment_top'></a><div id=\"comment_frame\"></div>" + "<script src=\"http://"
                + PropertiesHolder.get("commentServiceDomain") + "/scripts/comments.js\"></script>";
        return common_comment;
    }
    
    public String getTemplateCommentInclude(String url) {
        String comment3Uniqid = "var comment3Uniqid = '" + new MD5().get(url).toLowerCase() + "';";
        String common_comment = "<script>" + comment3Uniqid + "</script><a name='comment_top'></a><div id=\"comment_frame\"></div>" + "<script src=\"http://"
                + PropertiesHolder.get("commentServiceDomain") + "/scripts/comments.js\"></script>";
        return common_comment;
    }

    // 得到模板include语句
    private String getTemplateInclude(ChannelInfo channelInfo, TemplateInfo templateInfo) {
        return "<!--#include virtual=\"" + getTemplateIncludePath(channelInfo, templateInfo) + "\"-->";
    }

    // 得到js模板include语句
    private String getJsTemplateInclude(ChannelInfo channelInfo, TemplateInfo templateInfo) {
        return "document.write(\"<script type=\\\"text/javascript\\\" src=\\\"" + getTemplateIncludePath(channelInfo, templateInfo) + "\\\"></script>\");";

    }

    // 得到模板的包含用的地址（例如：/1011/m_154631096675.html）
    private String getTemplateIncludePath(ChannelInfo channelInfo, TemplateInfo templateInfo) {
        if (channelInfo == null || templateInfo == null)
            return "";
        String channelId = channelInfo.getId();
        Long templateId = templateInfo.getId();
        String alias = templateInfo.getAlias();
        String url = null;
        if (TemplateCategory.PUBLIC == templateInfo.getTemplateCategory()) { // 判断是否是公共模板
            url = PathUtil.getPublicTemplateInclude(channelId, templateId, alias);
        } else {
            url = PathUtil.getTemplateInclude(channelId, templateId, alias);
        }
        return url;
    }

    public String parserSpecialChannel(String content, String channelId) {
        if ("newgame".equals(channelId) || "news".equals(channelId) || "webgame".equals(channelId)) {
            content = replace(content);
        }
        return content;
    }

    /**
     * 对字符串进行替换操作
     * @param content
     * @return
     */
    private String replace(String content) {
        if (StringUtil.isEmpty(content)) {
            return "";
        }
        String[] article_replace = null;
        Pattern pattern = Pattern.compile("\\{\\[替换=([^\\]]+)\\]\\}", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        Matcher match = pattern.matcher(content);
        if (match.find()) {
            String[] rs = match.group(1).split(",");
            content = content.replace(match.group(0), "");
            if (rs != null && rs.length == 2)
                article_replace = rs;
        }
        if (article_replace != null) {
            content = content.replaceAll(article_replace[0], article_replace[1]);
        }
        return content;
    }

}
